.code16
.section ".bstext", "ax"
.global	_start, eprint, diskid

    cld
    sti
    ljmp	$0, $_start

diskid:	.byte	0x80

_start:
    movw	%cs, %ax            # 初始化段寄存器与堆栈
    movw	%ax, %ds
    movw	%ax, %es
    movw	%ax, %ss
    movl	$0x7bff, %esp
    movl	$0x7bff, %ebp

    lgdtl	(gdtptr)            # 初始化UnrealMode，提升段界限
    movl	%cr0, %eax
    orl	    $0x00000001, %eax
    movl	%eax, %cr0
    movw	$0x08, %bx
    movw	%bx, %ds
    movw	%bx, %es
    andl	$0xfffffffe, %eax
    movl	%eax, %cr0
    movw	$0, %bx
    movw	%bx, %ds
    movw	%bx, %es

1:	movb	diskid, %dl		    # dl -> 驱动器号
    movw	$0x0001, %cx		# cx -> 起始扇区号，0起始
    movw	$ld_sec_nm, %ax		# ax -> 扇区数
    movw	$buffer, %bx		# es:bx -> 缓冲区
    call	read

    movl	ld_magic, %eax
    cmpl	$0x4167C0E5, %eax
    je	2f
    movl	$magicerr, %esi
    jmp	epanic

2:	movl	$bss_size, %ecx
    movl	$bss_start, %edi
    movb	$0xcd, %al
    rep	stosb

    movl	$ldloaded, %esi
    calll	eprint

    call	LoaderMain

    movl	$stopmsg, %esi
    jmp	epanic

    # dh -> 0磁头; dl -> 0驱动器
    # ch -> 0磁道; cl -> 2扇区
    # es:bx -> 缓冲区
read:
    pushl	%eax
    movw	%ax, dap_sn	# AX -> 要读的扇区数
    movw	%es, %ax	# es:bx -> 指针
    shll	$16, %eax
    movw	%bx, %ax
    movl	%eax, dap_pt
    movw	%cx, dap_st
    movw	$dap, %si	# ds:si -> DAP
    mov	$0x42, %ah	    # ah -> 扩展读数据功能
    clc
    int	$0x13
    jc	1f
    popl	%eax
    ret
1:	movl	$diskerr, %esi
    jmp	epanic

    # 打印字符
    # si -> 零终止字符串
    # Ret: si -> 字符串尾
eprint:
    pushl	%esi
    pushw	%ax
    pushw	%bx
    movb	$0x0e, %ah
    movw	$0x0007, %bx
1:	lodsb
    testb	%al, %al
    jz	2f
    int	$0x10
    jmp	1b
2:	popw	%bx
    popw	%ax
    popl	%esi
    retl

epanic:
    calll	eprint
    # jmp     die
    # 死循环，程序终止
die:
    hlt
    jmp	die

.section	".bsdata", "a"

stopmsg:	.asciz "[PANIC] Boot loader return\n\r"
diskerr:	.asciz "[PANIC] Read disk error\n\r"
magicerr:	.asciz "[PANIC] Loader magic error\n\r"
ldloaded:	.asciz "[INFO ] Loader loaded\n\r"

dap:    .byte	0x10	# size
        .byte	0	    # unused
dap_sn: .word	0	    # number of sectors to be read
dap_pt:	.long	0	    # segment:offset pointer
dap_st:	.word	0	    # number of the start
        .word	0	    # high bits of start, unused there
        .long	0

gdt:	.quad	0
        .quad	0x00CF92000000FFFF
gdtend:

gdtptr:	.word	(gdtend - gdt - 1)
        .long	gdt
